<!DOCTYPE html>
<html lang='en'>
<head>
    <meta charset='UTF-8'>
    <title>Title</title>

    <style type="text/css">
    *{
        margin: 0;
	    padding: 0;
	    list-style: none;
	    font-size: 14px;
	    font-family: 宋体;
	    color: #000;

    }

    .container{
        background-color:yellowgreen;
        width: 100px;
        height:100px;
        border:2px solid

    }
        
    </style>

</head>

<body>

    <div class="container" >
        这是演示区

    </div>

<script>
/**
 * 
 * 1. debounce 防抖
 * 防抖，事件会频繁触发,保证事件只在最近一次触发后的预定时间后执行

 * 2. throttle节流
 * 节流，在事件不断的触发过程中，使事件间隔预定时间内才被执行一次
*/

    //防抖，事件会频繁触发,保证事件只在最近一次触发后的预定时间后执行
    let count =1;
    let containers = document.getElementsByClassName('container');
    container=containers[0];
    // console.log(containers);

    function getUserAction(e) {
        container.innerHTML = count++;
       // console.log(e);
    };

    //表示在最新的一次触发后1秒内才执行一次函数getUserAction

    let debounce = debounce5;
    let result = debounce(getUserAction,1000,true);
    container.onmousemove = function(){
        var res = result();
        console.log(res);
    }

    // container.onmousemove = debounce(getUserAction,1000,true);


//第1版 常规
function debounce1(func, wait) {
	var timeout; //用来标记定时器，
	return function () {
        // 事件有被触发了，就重置计时器，即删除之前的计时器clearTimeout，重新设置setTimeout
        clearTimeout(timeout) 
        
        //定时启动的返回值是一个该定时器上午唯一ID标志，用来取消该定时器。
		timeout = setTimeout(func, wait);
	}
}



//第2版
    function debounce2(func,wait){
        let timeout;

        return function(){

            // console.log(this); //就是container对应的div元素
            let context =this;
             
            clearTimeout(timeout);

            //这种方式确保了执行写函数是被相应的触发元素调用的；
            timeout = setTimeout(function (){
                func.apply(context);
            },wait);
        }
    }

// 第三版
function debounce3(func, wait) {
    var timeout;
    return function () {
        var context = this;
        var args = arguments;
        console.log(args);
        clearTimeout(timeout)

        //这种方式不仅绑定了触发的对象 同时也将参数传进去了
        timeout = setTimeout(function(){

            //这里相当于表示func函数是由context对象调用，并传参数 数组args
                func.apply(context, args)
        }, wait);
    }
}



// 第四版 添加immediate参数，让函数能够立刻执行，仅当事件停止触发n秒后，才能重新触发
function debounce4(func, wait, immediate) {

    var timeout;

    return function () {
        var context = this;
        var args = arguments;
        console.log(args);
        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 如果已经执行过，不再执行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
    }
}


// 第五版  * 添加函数返回值
function debounce(func, wait, immediate) {

    var timeout, result;

    return function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 如果已经执行过，不再执行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) result = func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
        return result;
    }
}








</script>
</body>
</html>